package org.apache.ibatis.type;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

@MappedTypes(List.class)
public class ListTypeHandler extends BaseTypeHandler<List> {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, List list, JdbcType jdbcType) throws SQLException {
        if(list == null){
            preparedStatement.setString(i, null);
        }
        else{

            JSONArray array = (JSONArray)JSON.toJSON(list);
            JSONObject json = new JSONObject(true);
            if(array.size() == 0){
                preparedStatement.setString(i, json.toJSONString());
            }
            else{
                Object object = list.get(0);
                json.put("@class", object.getClass().getTypeName());
                json.put("array", array);
                preparedStatement.setString(i, json.toJSONString());
            }

        }
    }

    @Override
    public List getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
        String value = resultSet.getString(columnName);
        if(value == null){
          return null;
        }
        JSONObject json = JSON.parseObject(value);
        if(json.size() ==0 ){
            return new ArrayList();
        }
        String classPath = json.getString("@class");
        json.remove("@class");
        try{
          Class<?> clazz = Class.forName(classPath);
          return JSONArray.parseArray(json.getString("array"), clazz);

        }
        catch (ClassNotFoundException ex){
          logger.error(ex.getMessage(), ex);
        }
        return null;
    }

    @Override
    public List getNullableResult(ResultSet resultSet, int i) throws SQLException {
        return null;
    }

    @Override
    public List getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
        return null;
    }
}